今日的程式碼 => GITHUB
這邊我想要介紹如何切換語言、設定 App 初始的語言,且下此開啟 App 時也會記住已經被切換過的語言。
這邊的教學,功能正常,但寫法不一定是最好的。這邊推薦另外的套件
  flutter_localizations:
    sdk: flutter
  shared_preferences: ^2.0.7
- - - - - - - - - - - - - - - - - - - - -
  assets:
    - language/
建立一個 language 在專案目錄底下建立兩個 Json
{
 "name": "flutter_localizations example",
 "introduce": "Hello"
}
{
 "name": "語言切換範例",
 "introduce" : "你好呀"
}
會給予 sharedpreferences 一個預設的語言 data(zh),手機一打開時,會在 didChangeDependencies 裡面去讀取 sharedpreferences,進而去設定 local 的地區是屬於什麼。
supportedLocales = App 要支援的語言localizationsDelegates = 委託確保加載正確語言的本地化數據localeResolutionCallback = 檢查手機是否支援這個語言locale = 現在手機的語言是什麼AppLocalizations = 是我們自己建立管理語言的一個 class
class MyApp extends StatefulWidget {
  MyApp({Key? key}) : super(key: key);
  @override
  _MyAppState createState() => _MyAppState();
  /// 當地區更改時,重新設定地區,當使用者按下變換語言時,會觸發。
  static void setLocale(BuildContext context, Locale newLocale) {
    _MyAppState? state = context.findAncestorStateOfType<_MyAppState>();
    state!.changeLocale(newLocale);
  }
}
class _MyAppState extends State<MyApp> {
  Locale _locale = new Locale.fromSubtags(languageCode: 'zh');
  /// 更改地區
  void changeLocale(Locale locale) {
    setState(() {
      this._locale = locale;
    });
  }
  @override
  void didChangeDependencies() async {
    super.didChangeDependencies();
    final languageApp = AppLocalizations();
    final localeKey = await languageApp.readLocaleKey();
    if (localeKey == "en") {
      this._locale = new Locale("en", "EN");
    } else {
      this._locale = new Locale.fromSubtags(languageCode: 'zh');
    }
    setState(() {});
  }
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        supportedLocales: [
          Locale('en', 'US'),
          const Locale.fromSubtags(languageCode: 'zh'),
        ],
        // These delegates make sure that the localization data for the proper language is loaded
        // 委託確保加載正確語言的本地化數據
        localizationsDelegates: [
          // This class will be added later
          // A class which loads the translations from JSON files
          AppLocalizations.delegate,
          // A class which loads the translations from JSON files
          GlobalMaterialLocalizations.delegate,
          // Built-in localization of basic text for Material widgets
          GlobalWidgetsLocalizations.delegate,
        ],
        locale: _locale,
        // Returns a locale which will be used by the app
        localeResolutionCallback: (locale, supportedLocales) {
          // Check if the current device locale is supported
          // 檢查手機是否支援這個語言
          for (var supportedLocaleLanguage in supportedLocales) {
            if (supportedLocaleLanguage.languageCode == locale?.languageCode &&
                supportedLocaleLanguage.countryCode == locale?.countryCode) {
              return supportedLocaleLanguage;
            }
          }
          // If device not support with locale to get language code then default get first on from the list
          return supportedLocales.first;
        },
        home: HomePage());
  }
}
class AppLocalizations {
  final Locale locale;
  AppLocalizations({this.locale = const Locale.fromSubtags(languageCode: 'zh')});
  /// Helper method to keep the code in the widgets concise
  /// Localizations are accessed using an InheritedWidget "of" syntax
  /// 訪問本地化
  static AppLocalizations? of(BuildContext context) {
    return Localizations.of<AppLocalizations>(context, AppLocalizations);
  }
  /// 儲存 SharedPreferences
  void keepLocaleKey(String localeKey) async {
    final _prefs = await SharedPreferences.getInstance();
    await _prefs.remove("localeKey");
    await _prefs.setString("localeKey", localeKey);
  }
  /// 讀取 SharedPreferences
  Future<String> readLocaleKey() async {
    final _prefs = await SharedPreferences.getInstance();
    // 初始化最一剛開始的語言
    return _prefs.getString("localeKey")??'zh';
  }
  
  /// 更改語言,重新設定語言
  void setLocale(BuildContext context, Locale locale) async {
    // keep value in shared pref
    keepLocaleKey(locale.languageCode);
    print("key language :${locale.languageCode}");
    MyApp.setLocale(context, locale);
  }
  /// Static member to have a simple access to the delegate from the MaterialApp
  /// 提供 Main Page 可以直接訪問。
  static const LocalizationsDelegate<AppLocalizations> delegate =
  _AppLocalizationsDelegate();
  late Map<String, String> _localizedStrings;
  /// Load the language JSON file from the "lang" folder
  /// 讀取 Json 格式
  Future<bool> load() async {
    String jsonString =
    await rootBundle.loadString('language/${locale.languageCode}.json');
    Map<String, dynamic> jsonMap = json.decode(jsonString);
    _localizedStrings = jsonMap.map((key, value) {
      return MapEntry(key, value.toString());
    });
    return true;
  }
  /// This method will be called from every widget which needs a localized text
  /// 提供每一個需要轉換語言的文字
  String translate(String key) {
    return _localizedStrings[key]!;
  }
}
/// LocalizationsDelegate is a factory for a set of localized resources
/// In this case, the localized strings will be gotten in an AppLocalizations object
/// 本地化的字符串將在 AppLocalizations 對像中獲取
class _AppLocalizationsDelegate
    extends LocalizationsDelegate<AppLocalizations> {
  // This delegate instance will never change (it doesn't even have fields!)
  // It can provide a constant constructor.
  const _AppLocalizationsDelegate();
  /// 之泉的語言代碼
  @override
  bool isSupported(Locale locale) {
    // Include all of your supported language codes here
    return ['en', 'zh'].contains(locale.languageCode);
  }
  /// 讀取 Json
  @override
  Future<AppLocalizations> load(Locale locale) async {
    // AppLocalizations class is where the JSON loading actually runs
    AppLocalizations localizations = new AppLocalizations(locale: locale);
    await localizations.load();
    return localizations;
  }
  /// 使否重新 reload
  @override
  bool shouldReload(_AppLocalizationsDelegate old) => false;
}
Text(AppLocalizations.of(context)!.translate('introduce')),
AppLocalizations localeApp = AppLocalizations();
// 之後再按鈕的 onPressed 裡面 
onPressed: () async {
  if (await localeApp.readLocaleKey() == "zh") {
    localeApp.setLocale(context, Locale("en", "EN"));
  } else {
    localeApp.setLocale(
    context, Locale.fromSubtags(languageCode: 'zh'));
  }
}